home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
COMM
/
RPL60
/
RPLPAT.INC
< prev
next >
Wrap
Text File
|
1992-12-31
|
12KB
|
312 lines
{*}
{*source code copyright (c) 1985, by TurboPower Software*}
{*}
{*}
procedure WritePat(PatRec : PatPtr);
{-list the pattern list starting at patrec}
var
j : PatPtr;
begin
j := PatRec;
while j <> nil do begin
case j^.Tok of
tClosure : Wr(Closure);
tLitChar : Wr(j^.One);
tCcl : Wr(Ccl+j^.StrPtr^+CclEnd);
tnCcl : Wr(Ccl+Negate+j^.StrPtr^+CclEnd);
tBol : Wr(Bol);
tEol : Wr(Eol);
tAny : Wr(Any);
tbTag : Wr(BTag);
teTag : Wr(ETag);
tGroup : begin
Wr(BGroup);
WritePat(j^.NestPtr);
Wr(EGroup);
end;
tDitto : begin
Wr(Ditto+'('+j^.One+')');
end;
tMaybeOne : begin
Wr(MaybeOne);
end;
end;
if j^.NexTok then Wr(Alter);
j := j^.Next;
end;
end; {writepat}
function GetPat(var arg : PatLine; var PatList : PatPtr) : Boolean;
{-convert argument into a pattern list, pointed to by patlist}
{-return true if successful}
var
TagOn : Boolean;
function MakePat(var arg : PatLine; Start : Integer; Delim : Char; var PatList : PatPtr) : Integer;
{-make a pattern list from arg[i], starting at start, ending at delim}
{-return 0 if error, last char position in arg if OK}
var
i : Integer;
nLastj, Lastj, tj, j : PatPtr;
Done : Boolean;
c : Char;
ts : LongString;
tTok : Tokens;
procedure AddPat(Tok : Tokens; Lastj : PatPtr; var j : PatPtr; s : LongString);
{-add a token record to the pattern list}
{-s contains a literal character or an expanded character class}
function CleanUpCase(var s : LongString) : LongString;
{-convert string to uppercase and remove duplicates}
var
i : Integer;
c : Char;
tOut : LongString;
begin
tOut := '';
for i := 1 to Length(s) do begin
c := UpCaseMac(s[i]);
if Pos(c, tOut) = 0 then tOut := tOut+c;
end;
CleanUpCase := tOut;
end; {cleanupcase}
begin
New(j); {allocate a new pointer for this token}
j^.Tok := Tok; {save token type}
j^.NexTok := False; {default to non-alternation}
j^.NestPtr := nil; {nestptr and next are filled in later}
j^.Next := nil;
Lastj^.Next := j; {hook up the previous token}
case Tok of
tNil, tAny, tBol, tEol, tGroup, tbTag, teTag :
begin
j^.One := Null;
j^.StrPtr := nil;
end;
tLitChar :
begin
if IgnoreCase then j^.One := UpCaseMac(s[1]) else j^.One := s[1];
j^.StrPtr := nil;
end;
tCcl, tnCcl :
begin
j^.One := Null;
if IgnoreCase then s := CleanUpCase(s);
New(j^.StrPtr);
j^.StrPtr^ := s;
end;
else
WrL('addpat:can''t happen');
Halt;
end;
end; {addpat}
function GetCcl(var arg : PatLine; var i : Integer;
{-} var s : LongString; var tTok : Tokens) : Boolean;
{-expand a character class starting at position i of arg into a string s}
{return a token type (tccl or tnccl)}
{return i pointing at the end of class character}
{return true if successful}
procedure DoDash(Delim : Char; var arg : PatLine; var i : Integer; var s : LongString);
{-expand the innards of the character class, including dashes}
{stop when endc is found}
{return a string s with the expansion}
var
c, cl, cn : Char;
j, k : Integer;
procedure AddStr(c : Char; var j : Integer; var s : LongString);
{-append a character c onto string s and increment position}
begin
j := Succ(j);
s[j] := c;
end; {addstr}
function IsAlphaNum(c : Char) : Boolean;
{-return true if character is in a-z, A-Z, or 0-9}
begin
if (c >= 'a') and (c <= 'z') then IsAlphaNum := True
else if (c >= 'A') and (c <= 'Z') then IsAlphaNum := True
else if (c >= '0') and (c <= '9') then IsAlphaNum := True
else IsAlphaNum := False;
end; {isalphanum}
begin
j := 0;
while (arg[i] <> Delim) and (arg[i] <> EndStr) do begin
c := arg[i];
if (c = Esc) then begin
if (arg[Succ(i)] <> EndStr) then begin
i := Succ(i);
c := arg[i];
case c of
lSpace : AddStr(#32, j, s);
lTab : AddStr(#9, j, s);
lBackSpace : AddStr(#8, j, s);
lReturn : AddStr(#13, j, s);
lFeed : AddStr(#10, j, s);
lInput : AddStr(#60, j, s);
lOutput : AddStr(#62, j, s);
lPipe : AddStr(#124, j, s);
else
AddStr(c, j, s);
end;
end else
{escape must be the character}
AddStr(Esc, j, s);
end else if c <> Dash then
{literal character}
AddStr(c, j, s)
else if (j = 0) or (arg[Succ(i)] = Delim) then
{literal dash at begin or end of class}
AddStr(Dash, j, s)
else begin
{dash in middle of class}
cl := arg[Pred(i)];
cn := arg[Succ(i)];
if IsAlphaNum(cl) and IsAlphaNum(cn) and (cl <= cn) then begin
{legal dash to be expanded}
for k := (Ord(cl)+1) to Ord(cn) do AddStr(Chr(k), j, s);
{move over the end of dash character}
i := Succ(i);
end else
{dash must be a literal}
AddStr(Dash, j, s);
end;
i := Succ(i);
end;
s[0] := Chr(j);
end; {dodash}
begin {getccl}
i := Succ(i); {skip over start of class character}
if arg[i] = Negate then begin
tTok := tnCcl;
i := Succ(i);
end else tTok := tCcl;
{expand the character class}
DoDash(CclEnd, arg, i, s);
GetCcl := (arg[i] = CclEnd);
end; {getccl}
begin {makepat}
New(PatList); {starter point for patlist}
PatList^.Tok := tNil; {put a nil token at the beginning}
PatList^.NexTok := False;
Lastj := PatList;
nLastj := nil;
i := Start; {start point of pattern string}
Done := False;
while not(Done) and (arg[i] <> Delim) and (arg[i] <> EndStr) do begin
c := arg[i];
if c = Any then AddPat(tAny, Lastj, j, c)
else if (c = Bol) then AddPat(tBol, Lastj, j, '')
else if (c = Eol) then AddPat(tEol, Lastj, j, '')
else if (c = Ccl) then begin
Done := (GetCcl(arg, i, ts, tTok) = False);
if Done then WrL('problem in expanding character class');
AddPat(tTok, Lastj, j, ts);
end else if (c = Alter) then begin
if (nLastj = nil) or
((nLastj^.Tok <> tClosure) and (nLastj^.Tok <> tMaybeOne)) then begin
{flag the current token as non-critical, i.e., "next is OK"}
Lastj^.NexTok := True;
end else begin
{alternation immediately after a closure is probably not desired}
{e.g., [a-z]*#[0-9] would internally produce ([a-z]#[0-9])*}
WrL('alternation cannot immediately follow a closure marker');
Done := True;
end;
end else if (c = BGroup) then begin
AddPat(tGroup, Lastj, j, '');
{recursive branch off the list}
i := MakePat(arg, Succ(i), EGroup, tj);
if i > 0 then
j^.NestPtr := tj
else begin
{didn't find egroup}
WrL('unbalanced nesting parentheses');
Done := True;
end;
end else if (c = BTag) and not(TagOn) then begin
AddPat(tbTag, Lastj, j, '');
TagOn := True;
end else if (c = ETag) and TagOn then begin
AddPat(teTag, Lastj, j, '');
TagOn := False;
end else if ((c = Closure) or (c = ClosurePlus) or (c = MaybeOne))
and (i > Start) then begin
if (Lastj^.Tok in [tBol, tEol, tMaybeOne, tClosure]) then begin
{error, can't have closure after any of these}
WrL('closure cannot immediately follow BegOfLine, EndOfLine or another closure');
Done := True;
end else begin
if (c = ClosurePlus) then begin
{insert an extra copy of the last token before the closure}
New(tj);
nLastj^.Next := tj;
tj^ := Lastj^;
nLastj := tj;
end;
{insert the closure between next to last and last token}
New(tj);
nLastj^.Next := tj;
if c = MaybeOne then tj^.Tok := tMaybeOne else tj^.Tok := tClosure;
tj^.One := Null; tj^.StrPtr := nil; tj^.NestPtr := nil;
tj^.Next := Lastj;
tj^.NexTok := False;
{set j and lastj back into sequence}
j := Lastj;
Lastj := tj;
end;
end else begin
if c = Esc then begin
{skip over escape character}
i := Succ(i);
c := arg[i];
case c of
lSpace : AddPat(tLitChar, Lastj, j, #32);
lNewline : begin
AddPat(tLitChar, Lastj, j, #13);
nLastj := Lastj;
Lastj := j;
AddPat(tLitChar, Lastj, j, #10);
end;
lTab : AddPat(tLitChar, Lastj, j, #9);
lBackSpace : AddPat(tLitChar, Lastj, j, #8);
lReturn : AddPat(tLitChar, Lastj, j, #13);
lFeed : AddPat(tLitChar, Lastj, j, #10);
lInput : AddPat(tLitChar, Lastj, j, #60);
lOutput : AddPat(tLitChar, Lastj, j, #62);
lPipe : AddPat(tLitChar, Lastj, j, #124);
lWordDelim : AddPat(tCcl, Lastj, j, wDelimString);
lHex : AddPat(tCcl, Lastj, j, '0123456789ABCDEF');
else
AddPat(tLitChar, Lastj, j, c);
end;
end else AddPat(tLitChar, Lastj, j, c);
end;
nLastj := Lastj;
Lastj := j;
if not(Done) then i := Succ(i);
end; {of looking through pattern string}
if Done or (arg[i] <> Delim) then begin
MakePat := 0;
WrL('error detected near end of '+Copy(arg, 1, i));
end else MakePat := i;
end; {makepat}
begin {getpat}
TagOn := False;
GetPat := (MakePat(arg, 1, EndStr, PatList) > 0);
if TagOn then begin
GetPat := False;
WrL('pattern error: unbalanced tag marker');
end;
end; {getpat}